﻿using System.Collections.Concurrent;
using System.Reflection;

namespace LS.Screening.UI.Common
{
    /// <summary>
    /// Class描述信息
    /// </summary>
    public class ClassDescribe
    {
        private static ConcurrentDictionary<Type, ClassDescribe> classDescribeCache = new ConcurrentDictionary<Type, ClassDescribe>();

        /// <summary>
        /// 类型全称[assembly,classFullName]
        /// </summary>
        public string TypeFullName { get; set; }

        /// <summary>
        /// 类型名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 类型描述信息
        /// </summary>
        public string Display { get; set; }

        /// <summary>
        /// 标签信息
        /// </summary>
        public IEnumerable<Attribute> Attributes { get; internal set; }

        /// <summary>
        /// 型属性信息列表[业务实体关键字段会被过滤掉]
        /// </summary>
        public List<PropertyDescribe> PropertyDescribes { get; set; }

        /// <summary>
        /// 获取指定类型的标签定义
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T GetAttribute<T>() where T : Attribute
        {
            return (T)Attributes.FirstOrDefault((Attribute p) => p.GetType().IsAssignableTo(typeof(T)));
        }

        /// <summary>
        /// 获取类型的描述信息
        /// </summary>
        /// <param name="type"></param>
        /// <param name="bindingFlags"></param>
        /// <returns></returns>
        public static ClassDescribe Get(Type type, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance)
        {
            if (classDescribeCache.ContainsKey(type))
            {
                return classDescribeCache[type];
            }

            lock (classDescribeCache)
            {
                if (classDescribeCache.ContainsKey(type))
                {
                    return classDescribeCache[type];
                }

                ClassDescribe classDescribe = new ClassDescribe();
                classDescribe.Name = type.Name;
                classDescribe.TypeFullName = type.Assembly.GetName().Name + ";" + type.FullName;
                List<Attribute> list = new List<Attribute>();
                list.AddRange(type.GetCustomAttributes(inherit: true).Cast<Attribute>());
                classDescribe.Attributes = list;
                classDescribe.Display = type.GetDisplay();
                if (string.IsNullOrEmpty(classDescribe.Display))
                {
                    classDescribe.Display = type.Name;
                }

                PropertyInfo[] properties = type.GetProperties(bindingFlags);
                List<PropertyDescribe> list2 = new List<PropertyDescribe>();
                PropertyInfo[] array = properties;
                foreach (PropertyInfo pro in array)
                {
                    if (!Keywords.EntityIgnoreFields.Any((string p) => p.Equals(pro.Name, StringComparison.OrdinalIgnoreCase)))
                    {
                        PropertyDescribe propertyDescribe = new PropertyDescribe();
                        propertyDescribe.PropertyInfo = pro;
                        propertyDescribe.Attributes = pro.GetCustomAttributes(inherit: false).Cast<Attribute>().ToList();
                        propertyDescribe.Display = pro.GetDisplay();
                        if (string.IsNullOrEmpty(propertyDescribe.Display))
                        {
                            propertyDescribe.Display = propertyDescribe.PropertyInfo.Name;
                        }

                        list2.Add(propertyDescribe);
                    }
                }

                classDescribe.PropertyDescribes = list2;
                if (!classDescribeCache.ContainsKey(type))
                {
                    classDescribeCache.TryAdd(type, classDescribe);
                }

                return classDescribe;
            }
        }

        /// <summary>
        /// 获取属性的描述信息
        /// </summary>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public PropertyDescribe GetPropertyDesc(string propertyName)
        {
            string propertyName2 = propertyName;
            return PropertyDescribes.FirstOrDefault((PropertyDescribe p) => p.PropertyInfo.Name.Equals(propertyName2, StringComparison.OrdinalIgnoreCase));
        }

        /// <summary>
        /// 重写
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return Name + (string.IsNullOrEmpty(Display) ? string.Empty : ("[" + Display + "]")) + "(" + PropertyDescribes.Count + ")";
        }
    }
}
